package com.gitee.swsk33.lucenedemo.util;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.highlight.Highlighter;
import org.apache.lucene.search.highlight.QueryScorer;
import org.apache.lucene.search.highlight.SimpleFragmenter;
import org.apache.lucene.search.highlight.SimpleHTMLFormatter;

/**
 * Lucene查询操作实用工具类
 */
public class LuceneQueryUtils {

	/**
	 * 根据用户输入的查询词，构建用于全文检索的查询条件
	 *
	 * @param field     查询的字段
	 * @param queryText 查询词
	 * @param analyzer  分词器
	 * @return 查询条件，分词失败则为null
	 */
	public static Query buildQuery(String field, String queryText, Analyzer analyzer) throws Exception {
		// 首先进行分词
		String[] tokens = AnalyzerUtils.tokenize(analyzer, queryText);
		if (tokens.length == 0) {
			return null;
		}
		// 视情况组装条件
		// 若只有一个词，则构建通配符查询
		if (tokens.length == 1) {
			QueryParser parser = new QueryParser(field, analyzer);
			return parser.parse(String.format("%s*", tokens[0]));
		}
		// 若有多个词，则构建布尔查询
		BooleanQuery.Builder booleanQueryBuilder = new BooleanQuery.Builder();
		for (String term : tokens) {
			booleanQueryBuilder.add(new TermQuery(new Term(field, term)), BooleanClause.Occur.MUST);
		}
		return booleanQueryBuilder.build();
	}

	/**
	 * 返回查询匹配到的第一个所在句子
	 *
	 * @param query    查询条件
	 * @param analyzer 分词器对象
	 * @param document 查询的文档对象
	 * @param field    查询字段
	 * @return 匹配到的第一个句子，已高亮
	 */
	public static String getMatchHiLight(Query query, Analyzer analyzer, Document document, String field) throws Exception {
		// 创建高亮器（用于提取匹配句子）
		// 高亮格式使用HTML方式加粗
		Highlighter highlighter = new Highlighter(new SimpleHTMLFormatter("<b>", "</b>"), new QueryScorer(query));
		// 设定提取片段的长度
		highlighter.setTextFragmenter(new SimpleFragmenter(32));
		// 获取高亮匹配部分
		String content = document.get(field);
		// 移除换行符等
		return highlighter.getBestFragment(analyzer.tokenStream(field, content), content).replace("\n", "").replace("\r", "");
	}

}